// 程序的入口点
class Test {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个对象实例作为线程之间的同步锁
        Object locker = new Object();

        // 创建第一个线程，该线程将尝试获取锁并等待通知
        Thread t1 = new Thread(() -> {
            try {
                // 同步块，使用locker对象作为锁
                synchronized (locker) {
                    // 在等待前打印消息
                    System.out.println("wait之前");
                    // 调用wait方法，线程将释放锁并等待，直到其他线程调用notify或notifyAll方法
                    locker.wait();
                    // 在等待后打印消息
                    System.out.println("wait之后");
                }
            } catch (InterruptedException e) {
                // 捕获中断异常并打印堆栈跟踪
                e.printStackTrace();
            }

        });

        // 创建第二个线程，该线程将尝试获取锁并发出通知
        Thread t2 = new Thread(() -> {
            try {
                // 同步块，使用locker对象作为锁
                synchronized (locker) {
                    // 在发送通知前打印消息
                    System.out.println("notify之前");
                    // 使当前线程睡眠2秒，模拟某些操作的延迟
                    Thread.sleep(2000);
                    // 调用notify方法，唤醒一个在该锁上等待的线程
                    locker.notify();
                    // 在发送通知后打印消息
                    System.out.println("notify之后");
                }
            } catch (InterruptedException e) {
                // 捕获中断异常并打印堆栈跟踪
                e.printStackTrace();
            }
        });

        // 启动第一个线程
        t1.start();
        // 启动第二个线程
        t2.start();

    }
}